//
//  Pack.m
//  Urban Words
//
//  Created by Tim Brandin on 2011-12-09.
//  Copyright (c) 2011 __MyCompanyName__. All rights reserved.
//

#import "UWRequest.h"
#import "NSObject+SBJSON.h"
#import "UWApi.h"

@implementation UWRequest

@synthesize request, connection, delegate;

static NSString* kUserAgent = @"iPhone";

- (UWRequest *)initWithMethod:(NSString *)method atServer:(NSString *)server operation:(CRUD)operation
{
    self = [super init];
    if (self) {
        
        // make authorized requests
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        if ([defaults objectForKey:@"FBAccessTokenKey"]
            && [defaults objectForKey:@"FBExpirationDateKey"]) {
            
            NSRange questionMark = [method rangeOfString:@"?" options:NSCaseInsensitiveSearch];
            
            if (questionMark.location == NSNotFound) {
                method = [NSString stringWithFormat:@"%@?access_token=%@", method, [defaults objectForKey:@"FBAccessTokenKey"]];
            } else {
                method = [NSString stringWithFormat:@"%@&access_token=%@", method, [defaults objectForKey:@"FBAccessTokenKey"]];
            }
            
        }
        
        NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@/%@", server, method]];
    
        request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60.0];
        
        [request setHTTPMethod:[UWRequest crudToString:operation]];
        [request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
        [request setValue:kUserAgent forHTTPHeaderField:@"User-Agent"];
        
    }
    return self;
}

- (void)addListener:(id)object action:(SEL)selector
{
    action = selector;
    target = [object retain];
}

/**
 * return: YES if success, NO if request was already sent
 */
- (BOOL)setPayload:(NSDictionary *)payload
{
    if (connection != nil) {
        return NO;
    }
    
    NSData *data = [[payload JSONRepresentation] dataUsingEncoding:NSUTF8StringEncoding];
    
    [request setHTTPBody:data];
    
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    
    [data release];
    
    return YES;
}

- (void)start 
{
    // start only if not previously sent
    if (self.request != nil && (self.delegate != nil || target != nil) && connection == nil) {
        
        connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
        [connection start];
        
        if (connection) {
            receivedData = [[NSMutableData data] retain];
            /*
            NSLog(@"-> request sent: %@", request.URL);
            NSLog(@"-> request method: %@", request.HTTPMethod);
            NSLog(@"-> request headers: %@", [request.allHTTPHeaderFields JSONRepresentation]);
             */
        }
        else {
            NSLog(@"connection failed");
            
            if ([target respondsToSelector:action]) {
                
                [target performSelector:action withObject:nil];
                
            }
        }
    }
}

- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
{
    /*
    NSLog(@"-> request data-length: %i", bytesWritten);
     */
}

- (void)connection:(NSURLConnection *)conn didFailWithError:(NSError *)error 
{
    NSLog(@"connection failed");
    
    [receivedData setLength:0];
    [receivedData autorelease];
    
    if ([target respondsToSelector:action]) {
        
        [target performSelector:action withObject:receivedData];
        
        [target release];
        action = nil;
        
    } else if ([delegate respondsToSelector:@selector(connection:didFailWithError:)]) {
        
        [delegate connection:conn didFailWithError:error];
        
    }
    
    connection = nil;
    [request release];
}

- (void)connection:(NSURLConnection *)conn didReceiveData:(NSData *)data 
{
    /*
    NSLog(@"<- recevied data: %i", [data length]);
    */
    [receivedData appendData:data];
    
    if ([delegate respondsToSelector:@selector(connection:didReceiveData:)])
        [delegate connection:conn didReceiveData:data];
    
}

- (void)connection:(NSURLConnection *)conn didReceiveResponse:(NSURLResponse *)response
{
    /*
    NSLog(@"<- response-code: %i", [(NSHTTPURLResponse *)response statusCode]);
    NSLog(@"<- response-headers:: %@", [[(NSHTTPURLResponse *)response allHeaderFields] JSONRepresentation]);
    */
    if ([delegate respondsToSelector:@selector(connection:didReceiveResponse:)])
        [delegate connection:conn didReceiveResponse:response];

}

- (void)connectionDidFinishLoading:(NSURLConnection *)conn 
{
    /*
    NSLog(@"<- response-finished:");
    */
    [receivedData autorelease];
    
    if ([target respondsToSelector:action]) {
        
        [target performSelector:action withObject:receivedData];
        
        [target release];
        action = nil;
        
    } 
    else if ([delegate respondsToSelector:@selector(connectionDidFinishLoading:)]) {
        [delegate connectionDidFinishLoading:conn];
    }
    
    connection = nil;
    [request release];
}

- (void)dealloc
{
    [request dealloc];
    [connection dealloc];
}

+ (NSString *)crudToString:(CRUD)operation
{
    switch (operation) {
        case CREATE:
            return @"POST";
            break;
            
        case READ:
            return @"GET";
            
        case UPDATE:
            return @"PUT";
            
        case DELETE:
            return @"DELETE";
            
        default:
            break;
    }
}

@end
